package com.ai.fupincore.util;

import java.io.BufferedWriter;
import java.io.ByteArrayInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStreamWriter;
import java.io.StringWriter;
import java.io.Writer;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;

import org.apache.struts2.ServletActionContext;

import com.ai.frame.logger.Logger;
import com.ai.frame.logger.LoggerFactory;
import com.ai.fupincore.util.Constants.FTP_CONFIG;

import freemarker.template.Configuration;
import freemarker.template.DefaultObjectWrapper;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import freemarker.template.TemplateExceptionHandler;

/**
 * 
 * FREEMARKER工具类
 * 
 * 主要用来生成静态页面
 * 
 * @author ZSL
 *
 */
public class FreemarkerUtils {
	private static final Logger LOGGER = LoggerFactory.getServiceLog(FreemarkerUtils.class);
    private static Configuration cfg = null;

    /**
     * 获取FREEMARKER的配置 FREEMARKER本身支持classpath,目录和从ServletContext获取.
     * @return 返回Configuration对象
     */
    @SuppressWarnings("deprecation")
	private static Configuration getConfiguration() {
        if (null == cfg) {
            cfg = new Configuration();
            // 这里有三种方式读取
            // （一个文件目录）
            // 相对web的根路径来说 根目录
            cfg.setServletContextForTemplateLoading(ServletActionContext.getServletContext(), "freemarkerTpl");
            // setEncoding这个方法一定要设置国家及其编码，不然在flt中的中文在生成html后会变成乱码
            cfg.setEncoding(Locale.getDefault(), "UTF-8");
            
            // 设置对象的包装器
            cfg.setObjectWrapper(new DefaultObjectWrapper());
            // 设置异常处理器//这样的话就可以${a.b.c.d}即使没有属性也不会出错
            cfg.setTemplateExceptionHandler(TemplateExceptionHandler.IGNORE_HANDLER);

        }

        return cfg;
    }
    
    
    /**
     * 生成商品详情静态页面
     * 
     * @param data 渲染数据集合
     * @param prodId 商品编号
     * 
     * @return true/false
     */
    public  static boolean generateProdHtmlToFtp(Map<String,Object> data, String prodId) {
    	//文件名加后缀.html
    	String fileName=prodId+".html";
    	//商品的FTL文件名
    	String ftl="prod.ftl";
    	return generateHtmlToFtp(ftl,data,fileName);
    }
    
    
    /**
     * 
     * 按照模板样式传入动态数据生成静态网页，并上传到FTP服务器的对应目录。
     * 
     * @param ftl 模板文件名
     * @param data 渲染数据集合
     * @param fileName 生成文件名
     * 
     * @return true/false
     */
    @SuppressWarnings("deprecation")
	public  static boolean generateHtmlToFtp(String ftl, Map<String,Object> data, String fileName) {

        try {
            // 创建Template对象
            Configuration cfg = FreemarkerUtils.getConfiguration();
            Template template = cfg.getTemplate(ftl);
            //设置模板编号为UTF-8
            template.setEncoding("UTF-8");

            
            //在内存中声明字符串输出缓冲流
            StringWriter sw = new StringWriter(); 
            //FREEMARKER引擎渲染模板数据到StringWriter
            template.process(data, sw);
            //强制将缓冲里的数据写入流里，close时候也会自动刷新
            sw.flush();
            //转换StringWriter为InputStream（注意中文UTF-8编码）
            InputStream is = new ByteArrayInputStream(sw.toString().getBytes("UTF-8"));
            
			// FTP服务地址
			String hostIp = PropertiesUtil.getString(FTP_CONFIG.FTP_HOST_IP);
			// FTP端口
			int port = PropertiesUtil.getInt(FTP_CONFIG.FTP_HOST_PORT);
			// FTP用户账号
			String userName = PropertiesUtil.getString(FTP_CONFIG.FTP_HOST_USERNAME);
			// FTP用户密码
			String userPwd = PropertiesUtil.getString(FTP_CONFIG.FTP_HOST_USERPD);
			// FTP根目录(商品详情静态页面生成目录)
			String remotePath = PropertiesUtil.getString(FTP_CONFIG.FTP_PATH_PROD_HTML_UPLOAD);
			
		    //实例化FtpUtil对象
			FtpUtil ftpUtil = new FtpUtil("");
			
			// 上传到FTP对应的文件夹目录下
			ftpUtil.uploadFile(hostIp, port, userName, userPwd, remotePath, fileName, is);
            
			//关闭StringWriter
            sw.close();
   
        } catch (IOException e) {
        	LOGGER.error("","",e);
            return false;
        } catch (TemplateException e) {
        	LOGGER.error("","",e);
            return false;
        }catch (Exception e) {
        	LOGGER.error("","",e);
            return false;
		}
        return true;
    }
    
    
    
    /**
     * 按照模板样式传入动态数据生成静态网页,保存为本机某文件目录下的某文件
     * 
     * @param ftl 模板文件名,相对上面的模版根目录templates路径,例如/module/view.ftl templates/module/view.ftl
     * @param data 填充数据
     * @param targetFile 要生成的静态文件的路径,相对设置中的根路径,例如 "jsp/user/1.html"
     * @return
     */
    @SuppressWarnings("deprecation")
	public  static boolean createFile(String ftl, Map<String,Object> data, String targetFile) {
    	Writer out = null;
    	FileOutputStream fos = null; 
        try {
            // 创建Template对象
            Configuration cfg = FreemarkerUtils.getConfiguration();
            Template template = cfg.getTemplate(ftl);
            template.setEncoding("UTF-8");

            // 生成静态页面
            fos =new FileOutputStream(targetFile);
            out = new BufferedWriter(new OutputStreamWriter(fos, "UTF-8"));
            template.process(data, out);
            out.flush();
        } catch (IOException e) {
        	LOGGER.error("","",e);
            return false;
        } catch (TemplateException e) {
        	LOGGER.error("","",e);
            return false;
        }finally {
        	try {
				if (fos != null) {
					fos.close();
				}
				if (out != null) {
					out.close();
				}
			} catch (IOException e) {
				LOGGER.error("", "", e);
			}
		}
        return true;
    }
    
    
    /**
     * 此工具类的主函数
     * (主要提供演示如何使用类和方法生成静态页面并上传到FTP,
     * 
     * 1、具体FTP的架设，自己本机测试，需要本机搭建一个FTP服务，推荐有Serv-U，自己可以去百度下载。
     * 具体的FTP相关参数在项目配置文件system.properties中配置，包含以下目5项：
     * 
     *  #FTP主机的IP地址
     * 	FTP_HOST_IP=127.0.0.1
     * 
     *  #FTP主机的端口号
     * 	FTP_HOST_PORT=21
     * 
     *  #连接FTP主机的账户
     * 	FTP_HOST_USERNAME=root
     * 
     *  #连接FTP主机的密码
     * 	FTP_HOST_USERPWD=000000
     * 
     *  #FTP服务器-商品详情静态页面保存目录
     * 	FTP_PATH_PROD_HTML_UPLOAD=/items
     * 	
     *  2、关于模板文件的存放目录，是在当前WEB项目根目录下新建了个freemarkerTpl文件夹，固定商品模板名称为prod.ftl
     *  具体此FTL模板文件的编写根据实际情况
     *  对于FREEMARKER模板的常用语法，也在此文件下有个ftl_demo_usg.html可供参考,还有个PDF文档也可参考。
     *  
     *  
     *  
     *  3、对于成功生成静态页面并上传到FTP目录下的页面，如何访问，需要搭建个WEB服务器，比如:NGINX提供静态页面的对外访问服务。
     *  比如：商品编号为100001的产品，生成到FTP的目录文件为：items/100001.html，则通过NGINX访问请求地址为：
     *  http://127.0.0.1:8081/items/100001.html
     *  
     *  也就是web85前端，生成的商品列表的元素为：<a href="${NGINX访问前缀}/items/100001.html">小米4</a>
     *  例如：
     *  <a href="http://127.0.0.1:8081/items/100001.html">小米4</a>
     * 
     * )
     * 
     * 考虑到暂时只有个商品详情页面需要生成静态HTML，提供了一个generateProdHtmlToFtp方法，
     * 专供生成固定的商品详情页面。方法里已经固定写死了模板的名字：prod.ftl
     * 
     * 
     * 小工具提示：
     * 在eclipse中编辑FTL模板文件，有一个插件可以安装，会有智能提醒，具体如何在线和离线安装。请参照附件。
     * 
     * 
     * @param args
     */
    public static void main(String[] args){
    	
    	 //##################以下为调用方式#######################
    	 //注意以下代码在此时不可执行的，主要演示调用代码，因为生成模板必须依赖ServletContext上下文找到模板文件所在位置
    	 //可以把以下代码放到ECP的ACTION下LoginAction.java的index方法，打开页面点击登录按钮试试。
   	 	 //######################################################

    	 //注意：对于模板页面有的标签，但是渲染数据集合MAP里没提供的，会报错提示未被定义。但是最终会生成静态页面。只是某一部分没数据。
    	 //例子模板里的user对象和商品对象测试在这就不创建自己根据实际模板来做。
    	 
		 //http://127.0.0.1:8081/page/items/100001.html
		 /*-------------------------------------------------------------*/
		 //填充模板数据 
	     Map<String, Object> root = new HashMap<>();  
	     root.put("csname", "我是张三");  
	     //产品编号
	     String prodId="100002";
	     
		 FreemarkerUtils.generateProdHtmlToFtp(root, prodId);
		 /*-------------------------------------------------------------*/
    }
	//添加一个私有构造函数来隐藏隐式公共构造函数
	private void Meaningless(){
		
	}
    
    
}